/*
 *  GeneticOptimizer.cpp
 *  Genetski
 *
 *  Created by Srđan Rašić on 11/17/11.
 *
 */

#include "GeneticOptimizer.h"
#include "Helper.h"
#include <vector>
#include <cmath>
#include <iostream>

GeneticOptimizer::GeneticOptimizer(Function& fun, Selection& selOper,
								   CrossoverOperator& crossOper, MutationOperator& mutatOper)
: _fun(fun), _selOper(selOper), _crossOper(crossOper), _mutatOper(mutatOper) {
	
}


void GeneticOptimizer::Initialize(int numberOfIndividuals, bool minimization, int precision) {
	_population = new Population(_fun, numberOfIndividuals, minimization, precision);
}

double pot(double base, double exponent) {
	double res = 1.0;
	while (exponent--)
		res *= base;
	return res;
}

std::vector<double> GeneticOptimizer::Optimize(unsigned int numberOfIterations) {
	for (int i = 0; i < numberOfIterations; i++) {
		std::vector<int> sel = _selOper.Select(*_population, 3);

		std::pair<Chromosome, Chromosome> children = _crossOper.Crossover((*_population)[sel[1]], (*_population)[sel[2]]);
		
		(*_population)[sel[0]] = children.first;
		
		_mutatOper.Mutate((*_population)[sel[0]]);
		
		if(_population->Fitness(sel[0]) > _population->Fitness(_population->BestIndividualIndex())) {
			_population->BestIndividualIndex() = sel[0];
			
			std::cout << "Iteration " << i << "/" << numberOfIterations << ": New optimum found: f(" << printVector(_population->ChromosomeValue(sel[0]))
			<< ") = " << _fun(_population->ChromosomeValue(sel[0])) << std::endl;
		}

	}
	
	int indMax = 0;
	for (int i = 1; i < _population->size(); i++)
		if ((*_population).Fitness(i) > (*_population).Fitness(indMax))
			indMax = i;
	
	std::vector<double> solution = _population->ChromosomeValue(indMax);
	return solution;
}